package org.flik.server.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.flik.client.main.service.UserService;
import org.flik.server.ObjectMapper;
import org.flik.server.ServerUtils;
import org.flik.server.bean.GenericBean;
import org.flik.server.bean.TicketDetailBean;
import org.flik.server.commonUtils.CommonUtils;
import org.flik.server.dto.IdName;
import org.flik.server.dto.InitialData;
import org.flik.server.dto.ProjectData;
import org.flik.server.dto.TicketChange;
import org.flik.server.dto.TicketDetail;
import org.flik.server.dto.TicketSummary;
import org.flik.server.dto.TiketSearchResult;
import org.flik.server.entity.FlikUser;
import org.flik.server.entity.Project;
import org.flik.server.entity.QueryParams;
import org.flik.server.entity.Ticket;
import org.flik.server.entity.TicketComment;
import org.flik.server.entity.TicketStatus;
import org.flik.server.entity.TicketType;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class UserServiceImpl  extends RemoteServiceServlet implements UserService {
	
	@PersistenceContext
	private EntityManager em;

	@SuppressWarnings("unchecked")
	@Override
	public InitialData fetchLoggedInUserInfo() {
		Long flikUserId = ServerUtils.getSessionLoginInfo(getThreadLocalRequest().getSession()).getFlikUserId(); 
		GenericBean genericBean = ServerUtils.lookupBean(GenericBean.class); 
		FlikUser flikUser = genericBean.find(FlikUser.class, flikUserId);
		String loggedInUserFullName = CommonUtils.constructFullName(flikUser.getFirstName() , flikUser.getLastName());
		List<Project> projects = genericBean.findWithNamedQuery(Project.FIND_ALL_PROJECTS);

		ArrayList<IdName> projectReturnList = new ArrayList<IdName>();
		for (Project project: projects)
			projectReturnList.add(new IdName(project.getId(), project.getDescription()));
//		TiketSearchResult tickets = null; 
//		if (projects != null && projects.size() > 0)
//			tickets = fetchTicketSearchResult(projects.get(0).getId(), 0, 50);
		return new InitialData(loggedInUserFullName, flikUserId, projectReturnList, 0);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public TiketSearchResult fetchTicketSearchResult(final Long projectId, int firstResult, int resultLimit) {
		List<TicketSummary> ticketShortList = new ArrayList<TicketSummary>();
		GenericBean genericBean = ServerUtils.lookupBean(GenericBean.class);
		List<Ticket> tickets = genericBean.findWithNamedQuery(Ticket.QUERY_FIND_TICKET, new HashMap<String, Object>(){{put(QueryParams.PROJECT_ID, projectId);}}, firstResult, resultLimit);
		for (Ticket ticket: tickets)
			ticketShortList.add(new TicketSummary(ticket.getId(), ticket.getReportedBy().getFirstName() + " " + ticket.getReportedBy().getLastName(), ticket.getTicketType().getDescription(), ticket.getTicketStatus().getDescription(), ticket.getAssignee().getFirstName() + " " + ticket.getAssignee().getLastName(), ticket.getProject().getDescription(), ticket.getTitle()));
		Long ticketCount = genericBean.getSingleResultWithNamedQuery(Ticket.QUERY_TICKET_COUNT, new HashMap<String, Object>(){{put(QueryParams.PROJECT_ID, projectId);}});
		TiketSearchResult searchResult = new TiketSearchResult(ticketShortList, ticketCount.intValue());
		return searchResult; 
	}

	@SuppressWarnings("unchecked")
	@Override
	public TicketDetail fetchTicketDetails(final Long ticketId) {
		
		GenericBean genericBean = ServerUtils.lookupBean(GenericBean.class);

		Ticket result = (Ticket) genericBean.findWithNamedQuery(Ticket.QUERY_TICKET_DETAIL, new HashMap<String, Object>(){{put("TICKET_ID", ticketId);}}).get(0);
		
		List<TicketComment> ticketCommentList = (List<TicketComment>)genericBean.findWithNamedQuery(TicketComment.QUERY_TICKET_COMMENTS, new HashMap<String, Object>(){{put("TICKET_ID", ticketId);}}); 
		
		List<TicketStatus> projectStatusList = (List<TicketStatus>)genericBean.findWithNamedQuery(TicketStatus.QUERY_PROJECT_STATUSES);
		
		List<TicketType> projectTicketTypeList = (List<TicketType>)genericBean.findWithNamedQuery(TicketType.QUERY_PROJECT_TICKET_TYPES);
		
		List<FlikUser> projectFlikUserList = (List<FlikUser>)genericBean.findWithNamedQuery(FlikUser.QUERY_PROJECT_USERS);
		
		return ObjectMapper.mapTicketDetail(
				result, 
				null, 
				ObjectMapper.mapCommentList(ticketCommentList), 
				ObjectMapper.mapProjectTicketTypeList(projectTicketTypeList), 
				ObjectMapper.mapProjectTicketStatusList(projectStatusList), 
				ObjectMapper.mapProjectFlikUserList(projectFlikUserList));
	}
	
	@Override
	public void save(final TicketChange ticketChange) {
		
		TicketDetailBean ticketDetailBean = ServerUtils.lookupBean(TicketDetailBean.class);
		ticketDetailBean.save(ticketChange, ServerUtils.getSessionLoginInfo(getThreadLocalRequest().getSession()).getFlikUserId());
	}

	@SuppressWarnings("unchecked")
	@Override
	public ProjectData fetchProjectData(Long projectId) {

		GenericBean genericBean = ServerUtils.lookupBean(GenericBean.class);

		List<TicketStatus> projectTicketStatusList = (List<TicketStatus>)genericBean.findWithNamedQuery(TicketStatus.QUERY_PROJECT_STATUSES);
		
		List<TicketType> projectTicketTypeList = (List<TicketType>)genericBean.findWithNamedQuery(TicketType.QUERY_PROJECT_TICKET_TYPES);
		
		List<FlikUser> projectFlikUserList = (List<FlikUser>)genericBean.findWithNamedQuery(FlikUser.QUERY_PROJECT_USERS);
		
		return new ProjectData(
				ObjectMapper.mapProjectTicketTypeList(projectTicketTypeList), 
				ObjectMapper.mapProjectTicketStatusList(projectTicketStatusList), 
				ObjectMapper.mapProjectFlikUserList(projectFlikUserList));
	}

	@Override
	public Long create(TicketChange ticketChange, Long projectId) {
		TicketDetailBean ticketDetailBean = ServerUtils.lookupBean(TicketDetailBean.class);
		return ticketDetailBean.create(ticketChange, ServerUtils.getSessionLoginInfo(getThreadLocalRequest().getSession()).getFlikUserId(), projectId);
	}
}